﻿using System;
using System.Linq.Expressions;
using System.Text;
using AutoMapper;
using CarAppDomain.Rule.Entities;
using CarAppDomain.Rule.IRepositories;
using CarAppDto.Rule.RuleConfigDtos;
using CarAppDto.Rule.RuleMappingDtos;
using CarAppService.Rule.IServices;
using D.Util.UtilCache;
using D.Util.UtilConfiguration;
using D.Util.UtilExpression;
using D.UtilCore.Dtos;
using D.UtilCore.JwtUtil;
using D.UtilCore.Models;
using D.UtilCore.Utils;
using D.UtilSqlsugarOrm;
using Microsoft.AspNetCore.Http;
using Microsoft.Win32;
using Newtonsoft.Json;

namespace CarAppDomain.Rule.Services
{
    /// <summary>
    /// 规则匹配项
    /// </summary>
    public class RuleMappingEntityService : BaseService<RuleMappingEntity>, IRuleMappingEntityService
    {
        private readonly IMapper _mapper;
        private readonly ICacheService _cache;
        private readonly IJwtService _tokenService;
        private readonly IRuleMappingEntityRepository _repository;
        private readonly IRuleConfigEntityRepository _repositoryRuleConfig;
        private readonly IHttpContextAccessor _httpContextAccessor;

        /// <summary>
        /// 构造注入
        /// </summary>
        public RuleMappingEntityService(IMapper mapper, ICacheService cache, IJwtService tokenService, IHttpContextAccessor httpContextAccessor, IRuleMappingEntityRepository repository
            , IRuleConfigEntityRepository repositoryRuleConfig)
        {
            // 用于base方法
            base._baseDal = repository;
            this._repository = repository;
            _cache = cache;
            _mapper = mapper;
            _tokenService = tokenService;
            _httpContextAccessor = httpContextAccessor;
            _repositoryRuleConfig = repositoryRuleConfig;
        }

        #region 增删改查


        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="reqModel"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> AddAsync(ReqAddRuleMapping reqModel)
        {

            if (reqModel.Details.ValueDetailsList != null && reqModel.Details.ReferenceDetails != null)
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "ValueDetailsList和ReferenceDetails不能同时有值" };
            if (reqModel.Details.ValueDetailsList == null && reqModel.Details.ReferenceDetails == null)
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "ValueDetailsList和ReferenceDetails不能同时为空" };

            //位置解析
            string regStr = "";
            if (!string.IsNullOrWhiteSpace(reqModel.RegStr))
                regStr = reqModel.RegStr;
            else
            {
                //位置转正则表达式
                RuleMappingValue keyVlues = reqModel.KeyValue;
                Dictionary<int, char> ruleDetailDic = new Dictionary<int, char>();
                string[] postionArry = keyVlues.Key.Split(',');
                if (postionArry.Length != keyVlues.Value.Length)
                    return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = $"Key:{keyVlues.Key}不对等Value:{keyVlues.Value}" };
                char[] valuesArray = keyVlues.Value.ToCharArray();
                for (int i = 0; i < postionArry.Length; i++)
                {
                    int postion;
                    if (!int.TryParse(postionArry[i], out postion))
                        return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = $"Postion：{postionArry[i]}错误" };
                    if (ruleDetailDic.ContainsKey(postion))
                        return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = $"Postion：{postionArry[i]}重复" };
                    else
                        ruleDetailDic.Add(postion, valuesArray[i]);
                }

                ruleDetailDic = ruleDetailDic.OrderBy(x => x.Key).ToDictionary();
                regStr = UtilExpression.ConvertRegularExpression(ruleDetailDic);
            }
            var exists = await _repository.ExistsAsync(m => m.RuleId == reqModel.RuleId && m.RegStr == regStr);
            if (exists)
            {
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "重复匹配项" };
            }
            if (!string.IsNullOrWhiteSpace(reqModel.RuleId))
            {
                exists = await _repositoryRuleConfig.ExistsAsync(m => m.Id == reqModel.RuleId);
                if (!exists)
                {
                    return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "规则信息不存在" };
                }
            }
            var insertEntity = _mapper.Map<ReqAddRuleMapping, RuleMappingEntity>(reqModel);
            insertEntity.RegStr = regStr;
            insertEntity.DeleteFlag = false;
            insertEntity.CreateTime = DateTime.Now;
            if (reqModel.KeyValue != null)
            {
                insertEntity.Key = reqModel.KeyValue.Key;
                insertEntity.Val = reqModel.KeyValue.Value;
            }
           
            insertEntity.Id = Guid.NewGuid().ToString();
            var dbres = await _repository.AddAsync(insertEntity);
            return dbres.NormalResponse();
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> DeleteAsync(List<string> ids)
        {
            var dbres = await _repository.DeleteAsync(m => ids.Contains(m.Id));
            return dbres.NormalResponse();
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="reqModel"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> UpdateAsync(ReqUpdateRuleMapping reqModel)
        {
            var updateEntity = await _repository.GetModelAsync(m => m.Id == reqModel.Id);
            if (updateEntity == null)
            {
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "该信息不存在" };
            }
            if (reqModel.Details.ValueDetailsList != null && reqModel.Details.ReferenceDetails != null)
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "ValueDetailsList和ReferenceDetails不能同时有值" };
            if (reqModel.Details.ValueDetailsList == null && reqModel.Details.ReferenceDetails == null)
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "ValueDetailsList和ReferenceDetails不能同时为空" };

            //位置解析
            string regStr = "";
            if (!string.IsNullOrWhiteSpace(reqModel.RegStr))
                regStr = reqModel.RegStr;
            else
            {
                //位置转正则表达式
                RuleMappingValue keyVlues = reqModel.KeyValue;
                Dictionary<int, char> ruleDetailDic = new Dictionary<int, char>();
                string[] postionArry = keyVlues.Key.Split(',');
                if (postionArry.Length != keyVlues.Value.Length)
                    return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = $"Key:{keyVlues.Key}不对等Value:{keyVlues.Value}" };
                char[] valuesArray = keyVlues.Value.ToCharArray();
                for (int i = 0; i < postionArry.Length; i++)
                {
                    int postion;
                    if (!int.TryParse(postionArry[i], out postion))
                        return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = $"Postion：{postionArry[i]}错误" };
                    if (ruleDetailDic.ContainsKey(postion))
                        return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = $"Postion：{postionArry[i]}重复" };
                    else
                        ruleDetailDic.Add(postion, valuesArray[i]);
                }

                ruleDetailDic = ruleDetailDic.OrderBy(x => x.Key).ToDictionary();
                regStr = UtilExpression.ConvertRegularExpression(ruleDetailDic);
            }
            var exists = await _repository.ExistsAsync(m =>m.Id!=reqModel.Id&& m.RuleId == reqModel.RuleId && m.RegStr == regStr);
            if (exists)
            {
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "重复匹配项" };
            }
            if (!string.IsNullOrWhiteSpace(reqModel.RuleId))
            {
                exists = await _repositoryRuleConfig.ExistsAsync(m => m.Id == reqModel.RuleId);
                if (!exists)
                {
                    return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "规则信息不存在" };
                }
            }
            updateEntity.Descption=reqModel.Descption;
            updateEntity.UpdateTime = DateTime.Now;
            updateEntity.UpdateUser = reqModel.UpdateUser;
            updateEntity.ValueDetails = JsonConvert.SerializeObject(reqModel.Details);
            updateEntity.RegStr = regStr;
            if (reqModel.KeyValue != null)
            {
                updateEntity.Key = reqModel.KeyValue.Key;
                updateEntity.Val = reqModel.KeyValue.Value;
            }
            var dbres = await _repository.UpdateAsync(updateEntity);
            return dbres.NormalResponse();
        }

        /// <summary>
        /// 获取详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ApiResult<RepRuleMapping>> GetAsync(string id)
        {
            var dbres = await _repository.GetModelAsync(m => m.Id == id);
            var res = _mapper.Map<RuleMappingEntity, RepRuleMapping>(dbres);

            if (!string.IsNullOrWhiteSpace(res.Key) && !string.IsNullOrWhiteSpace(res.Val))//值匹配和 正则匹配不同时显示到页面
                res.RegStr = "";

            return res.GetResponse();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="reqModel"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<RepRuleMapping>>> QueryListAsync(ReqGueryRuleMappingList reqModel)
        {

            Expression<Func<RuleMappingEntity, bool>> where = null;
            if (!string.IsNullOrEmpty(reqModel.RuleId))
            {
                where = where.And(m => m.RuleId.Contains(reqModel.RuleId));
            }
                
            var dbres = await _repository.GetListAsync(where);
            var res = _mapper.Map<List<RuleMappingEntity>, List<RepRuleMapping>>(dbres);             
            return res.GetResponse();
        }
        /// <summary>
        /// 获取分页
        /// </summary>
        /// <param name="reqModel"></param>
        /// <returns></returns>
        public async Task<ApiResult<PageModel<RepRuleMapping>>> QueryPagesAsync(ReqQueryRuleMappingPage reqModel)
        {
            Expression<Func<RuleMappingEntity, bool>> where = null;
            if (!string.IsNullOrEmpty(reqModel.RuleId))
            {
                where = where.And(m => m.RuleId.Contains(reqModel.RuleId));
            }

            var dbres = await _repository.GetPagesAsync(reqModel.PageSize, reqModel.PageNo, where, m => m.CreateTime);
         
            var res = new PageModel<RepRuleMapping>()
            {
                PageNo = dbres.PageNo,
                PageSize = dbres.PageSize,
                TotalCount = dbres.TotalCount,
                TotalPage = dbres.TotalPage,
                Data = _mapper.Map<List<RuleMappingEntity>, List<RepRuleMapping>>(dbres.Data)
            };
          
            return res.GetResponse();
        }
        #endregion 



        /// <summary>
        /// 将匹配详情转换为字符串，用于重复判断
        /// </summary>
        /// <param name="mappingDetails"></param>
        /// <returns></returns>
        public string ConvertVal(RuleMappingDetails mappingDetails)
        {
            List<string> valueList = new List<string>();
            if (mappingDetails.ValueDetailsList != null)
                valueList.AddRange(mappingDetails.ValueDetailsList.Select(a => a.Value).OrderBy(a => a).ToArray());
            else
                valueList.Add(mappingDetails.ReferenceDetails.Id);
            return string.Join(',', valueList);

        }

        /// <summary>
        /// 获取匹配详情
        /// </summary>
        /// <param name="rep"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<RepRuleMapping>>> GetRuleMappingByVIN(RepRuleConfigAndVIN rep)
        {
            var dbres = await _repository.GetRuleMappingByVINAsync(rep.RuleId,rep.VIN);
            var res = _mapper.Map<List<RuleMappingEntity>, List<RepRuleMapping>>(dbres);
            return res.GetResponse();
        }
    }
}
